package com.english.websocket.processor;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONPath;
import com.english.websocket.constants.ProjectConstants;
import com.english.websocket.pojo.RequestParamPojo;
import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class MediaTypeProcessor {
    private static final MediaTypeProcessor INSTANCE = new MediaTypeProcessor();

    public static MediaTypeProcessor getInstance() {
        return INSTANCE;
    }

    public List<RequestParamPojo> dealMediaData(File file, JSONObject reqData, String mediaValueJsonPath) throws IOException {
        String mediaType = mediaValueJsonPath.substring(mediaValueJsonPath.lastIndexOf(".") + 1);
        switch (mediaType){
            case ProjectConstants.TEXT:
                return parseDataForText(file);
            case ProjectConstants.IMAGE:
                return parseDataForImage(file);
            case ProjectConstants.AUDIO:
                return parseDataForAudio(file, reqData, mediaValueJsonPath);
            case ProjectConstants.VIDEO:
                return parseDataForVideo();
            default:
                throw new UnsupportedOperationException("不支持的媒体类型");
        }
    }

    /**
     * 解析文本文件流
     * @param file 传输文件
     * @return 数据段集合
     */
    private List<RequestParamPojo> parseDataForText(File file) throws IOException {
        List<String> contents = FileUtils.readLines(file, StandardCharsets.UTF_8);
        if (contents.isEmpty()) {
            return generateDefaultStreamMetaDataList();
        }

        List<RequestParamPojo> streamMetaDataList = new ArrayList<>();
        int size = contents.size();
        for (int i=0;i<size;i++) {
            byte[] bytes = contents.get(i).getBytes(StandardCharsets.UTF_8);
            streamMetaDataList.add(createStreamMetaData(bytes, i, size));
        }
        return streamMetaDataList;
    }

    /**
     * 解析图片文件流
     * @param file 传输文件
     * @return 数据段集合
     */
    private List<RequestParamPojo> parseDataForImage(File file) throws IOException {
        if (!file.isDirectory()) {
            throw new RuntimeException("流式能力需要传递一个图片集目录");
        }
        File[] files = file.listFiles();
        if (files == null || files.length == 0) {
            return generateDefaultStreamMetaDataList();
        }

        List<RequestParamPojo> requestParamPojoList = new ArrayList<>();
        int length = files.length;
        for (int i=0;i<length;i++) {
            byte[] bytes = FileUtils.readFileToByteArray(files[i]);
            requestParamPojoList.add(createStreamMetaData(bytes, i, length));
        }
        return requestParamPojoList;
    }

    /**
     * 解析音频文件流
     * @param file 传输文件
     * @param requestData 请求对象
     * @param jsonPath jsonPath路径
     */
    private List<RequestParamPojo> parseDataForAudio(File file, JSONObject requestData, String jsonPath) throws IOException {
        String parentJsonPath = jsonPath.substring(0, jsonPath.lastIndexOf("."));
        Object mediaJsonObject = JSONPath.eval(requestData, parentJsonPath);
        if (mediaJsonObject == null) {
            throw new RuntimeException("未获取到请求数据对象");
        }
        JSONObject audioFieldObject = (JSONObject)mediaJsonObject;
        String encoding = audioFieldObject.getString("encoding");
        Integer frameSize = audioFieldObject.getInteger("frame_size");
        if (encoding != null && encoding.startsWith("speex")) {
            //若是开源的请使用这段代码
           /* if (frameSize == null || frameSize<=0) {
                JSONPath.set(requestData, parentJsonPath+".frame_size", 60);
            }
            return buildStreamData(file, 120, true);*/
            //使用默认提供的样例
            return buildStreamData(file, 122, true);
        } else {
            return buildStreamData(file, 122, true);
        }
    }

    /**
     * 解析视频文件流
     * @return 数据段集合
     */
    private List<RequestParamPojo> parseDataForVideo() {
        //TODO 暂未实现
        throw new UnsupportedOperationException("暂不支持视频流式拆帧");
    }

    /**
     * 构建流式数据
     * @param file  传输文件
     * @param readLen 读取长度
     */
    public List<RequestParamPojo> buildStreamData(File file, Integer readLen, boolean isStreamMode) throws IOException {
        byte[] bytes = FileUtils.readFileToByteArray(file);
        if (bytes == null || bytes.length==0) {
            return generateDefaultStreamMetaDataList();
        }

        List<RequestParamPojo> requestParamPojoList = new ArrayList<>();
        if (!isStreamMode) {
            requestParamPojoList.add(createStreamMetaData(bytes, 0, 1));
        } else {
            int length = bytes.length;
            int inputLength = 0;
            if (readLen > length) {
                readLen = length;
            }
            int num = 1;
            while (inputLength + readLen <= length) {
                RequestParamPojo requestParamPojo = new RequestParamPojo();
                requestParamPojoList.add(requestParamPojo);
                if (num ==1) {
                    requestParamPojo.setStatus(ProjectConstants.STATUS_BEGIN);
                } else {
                    requestParamPojo.setStatus(ProjectConstants.STATUS_CONTINUE);
                }
                if (inputLength + readLen == length) {
                    requestParamPojo.setStatus(ProjectConstants.STATUS_END);
                }
                requestParamPojo.setByteContent(Arrays.copyOfRange(bytes,  inputLength,  inputLength + readLen));
                requestParamPojo.setDataLength(readLen);
                num = num + 1;
                inputLength = inputLength + readLen;
            }
            if (length > inputLength) {
                RequestParamPojo requestParamPojo = new RequestParamPojo();
                requestParamPojo.setByteContent(Arrays.copyOfRange(bytes,  inputLength,  length));
                requestParamPojo.setStatus(ProjectConstants.STATUS_END);
                requestParamPojo.setDataLength(length-inputLength);
                requestParamPojoList.add(requestParamPojo);
            }
        }
        return requestParamPojoList;
    }

    /**
     * 生成流式请求段
     * @param bytes 数据数组
     * @param index 数据段索引
     * @param length 数据段长度
     * @return 数据段对象
     */
    private RequestParamPojo createStreamMetaData(byte[] bytes, int index, int length) {
        RequestParamPojo requestParamPojo = new RequestParamPojo();
        requestParamPojo.setByteContent(bytes);
        requestParamPojo.setDataLength(bytes.length);
        if (index==length-1) {
            requestParamPojo.setStatus(ProjectConstants.STATUS_END);
        } else if (index==0) {
            requestParamPojo.setStatus(ProjectConstants.STATUS_BEGIN);
        } else {
            requestParamPojo.setStatus(ProjectConstants.STATUS_CONTINUE);
        }
        return requestParamPojo;
    }

    /**
     * 生成结束请求段
     */
    private static List<RequestParamPojo> generateDefaultStreamMetaDataList() {
        List<RequestParamPojo> streamMetaDataList = new ArrayList<>();
        RequestParamPojo streamMetaData = new RequestParamPojo();
        streamMetaDataList.add(streamMetaData);
        streamMetaData.setByteContent(new byte[0]);
        streamMetaData.setStatus(ProjectConstants.STATUS_END);
        streamMetaData.setDataLength(0);
        return streamMetaDataList;
    }


}
